package com.leochan.shuniu.database;

import java.util.ArrayList;

import com.leochan.shuniu.database.model.BaseModel;

/**
 * Database query pager.
 * 
 * @author Jerry
 * 
 * @param <T>
 */
public class Pager<T extends BaseModel> {
    public static final int DEFAULT_PAGE_SIZE = 12;

    private int totalDataCount;

    private int totalPageCount;

    private int currentPage = -1;

    private int pageSize = DEFAULT_PAGE_SIZE;

    private ListCircleItem<T> currentPageItem;

    private ArrayList<T> data;

    private Dao<T> dao = null;

    private String select = null;

    public Pager(int pageSize, Dao<T> dao, String select) {
        this.pageSize = pageSize;
        this.dao = dao;
        this.select = select;

        init();
    }

    @SuppressWarnings("unchecked")
    private void init() {
        /* query all recorder count */
        totalDataCount = dao.countBy(select, null);
        
        /* get page count */
        int pageCount = totalDataCount / pageSize;
        if (totalDataCount % pageSize != 0)
            pageCount++;
        totalPageCount = pageCount;

        /* prepare the first page */
        // ListCircleItem<T> circleItem0 = new ListCircleItem<T>();
        // circleItem0.pageIndex = 0;
        // ListCircleItem<T> circleItem1 = new ListCircleItem<T>();
        // circleItem1.pageIndex = 1;
        // ListCircleItem<T> circleItem_1 = new ListCircleItem<T>();
        // circleItem_1.pageIndex = -1;
        //
        // circleItem0.next = circleItem1;
        // circleItem1.next = circleItem_1;
        // circleItem_1.next = circleItem0;
        // circleItem0.previous = circleItem_1;
        // circleItem1.previous = circleItem0;
        // circleItem_1.previous = circleItem1;
        //
        // currentPageItem = circleItem0;

        currentPage = 0;
        data = _loadData(currentPage);
        // currentPageItem.list = dao.queryBy(select + " " + sqlLimit(0), null);

    }

    public int getTotalPageCount() {
        return totalPageCount;
    }

    public int getTotalDataCount() {
        return totalDataCount;
    }

    public int getCurrentPageIndex() {
        return currentPage;
    }

    public ArrayList<T> currentPage() {
        return data;
    }

    public ArrayList<T> nextPage() {
        return getPage(currentPage + 1);
    }

    public ArrayList<T> previousPage() {
        return getPage(currentPage - 1);
    }

    public ArrayList<T> getPage(int page) {
        if (page < 0 || page > totalPageCount - 1)
            return null;
        if (page == currentPage)
            return data;
        currentPage = page;
        return (data = _loadData(page));
    }

    /**
     * "limit x offset y" x: the max select item count, offset: skip offset
     * items for this query
     */
    private String sqlLimit(int page) {
        StringBuffer limit = new StringBuffer("limit ");
        limit.append(pageSize).append(" offset ").append(page * pageSize);
        return limit.toString();
    }

    private ArrayList<T> _loadData(int page) {
        return dao.queryBy(select + " " + sqlLimit(page), null);
    }

    private static class ListCircleItem<T> {
        ListCircleItem previous;
        ListCircleItem next;
        ArrayList<T> list;
        int pageIndex;
    }

}
